package cn.tedu.lbs.basic.web.service;

import cn.tedu.lbs.basic.web.repository.BusinessCategoryRepository;
import cn.tedu.lbs.basic.web.repository.BusinessRepository;
import cn.tedu.lbs.basic.web.utils.AuthenticationContextUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tarena.lbs.base.common.utils.Asserts;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.base.protocol.pager.PageResult;
import com.tarena.lbs.common.passport.enums.Roles;
import com.tarena.lbs.common.passport.principle.UserPrinciple;
import com.tarena.lbs.pojo.basic.param.BusinessParam;
import com.tarena.lbs.pojo.basic.po.BusinessPO;
import com.tarena.lbs.pojo.basic.query.BusinessQuery;
import com.tarena.lbs.pojo.basic.vo.BusinessCategoryVO;
import com.tarena.lbs.pojo.basic.vo.BusinessVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@Service
public class BusinessService {
    @Autowired
    private BusinessRepository businessRepository;
    public PageResult<BusinessVO> pageList(BusinessQuery query){
        //1.准备一个pageResult对象
        PageResult<BusinessVO> pageResult = new PageResult<>();
        pageResult.setPageNo(query.getPageNo());
        pageResult.setPageSize(query.getPageSize());
        //2.缺什么给什么 pageNo(query) pageSize(query) total(BusinessMapper count)
        //objects(List <BusinessVO> businessMapper List<BusinessPO> -> BusinessVO)
        //2.1 total sql select count(0) from lbs_business where 非空拼接 商家名称 负责人电话 时间范围
//        Long total = getTotal(query);
        //2.2 object select * from lbs_business where 非空拼接 商家名称 负责人电话 时间范围 limit from,size
//        List<BusinessVO> vos = getObjects(query);
//        pageResult.setTotal(total);
//        pageResult.setObjects(vos);
        PageInfo<BusinessPO> pageInfo = getPageInfo(query);
        //pageInfo有分页使用的所有属性 pageNo pageSize total objects
        pageResult.setTotal(pageInfo.getTotal());
        //从pageInfo获取本次分页查询的列表 pos
        List<BusinessPO> pos = pageInfo.getList();
        List<BusinessVO> vos = null;
        if (pos != null && pos.size()>0 ){
            //使用原来的集合pos做流映射处理
            vos=pos.stream().map(po->{
                //映射算法 返回新映射对象
                BusinessVO vo = new BusinessVO();
                BeanUtils.copyProperties(po,vo);
                return vo;
            }).collect(Collectors.toList());
        }
        pageResult.setObjects(vos);
        return pageResult;
    }

    private PageInfo<BusinessPO> getPageInfo(BusinessQuery query) {
        //希望通过 pageHelper查询 将属性total和objects全部查询出来 返回
        //以下 严格遵循分页插件 PageHelper的使用
        //1.开启分页
        PageHelper.startPage(query.getPageNo(),query.getPageSize());
        /*if (1==1){
            PageHelper.clearPage();
            return null;
        }*/
        //2.开启业务查询 只关心业务条件的 sql select * from lbs_business where query 非空条件
        QueryWrapper<BusinessPO> queryWrapper = generateQueryWrapper(query);
        List<BusinessPO> pos = businessRepository.list(queryWrapper);
        //pos实现类 已经不再是mybatis封装的 ArrayList是一个Page对象
        log.info("分页插件PageHelper查询结果类型：{}",pos.getClass().getName());
        //3.将开启了分页查询的结果 pos对象 交给插件的类型封装
        return new PageInfo(pos);

    }

    private QueryWrapper<BusinessPO> generateQueryWrapper(BusinessQuery query){
        QueryWrapper<BusinessPO> queryWrapper = new QueryWrapper<>();
        //根据query参数中的非空属性 拼接where
        if(query.getBusinessName()!=null){
            //where business_name like '%?%'
            queryWrapper.like("business_name",query.getBusinessName());
        }
        if(query.getBusinessHeadPhone()!=null){
            queryWrapper.eq("business_head_phone",query.getBusinessHeadPhone());
        }
        if(query.getBusinessStatus()!=null){
            queryWrapper.eq("business_status",query.getBusinessStatus());
        }
        if(query.getStartingTime()!=null){
            //where entry_time >= ? ge(greater than and equals) le(less than and equals)
            queryWrapper.ge("entry_time",query.getStartingTime());
        }
        if(query.getEndTime()!=null){
            queryWrapper.le("entry_time",query.getEndTime());
        }
        return queryWrapper;
    }
    @Autowired
    private BusinessCategoryRepository businessCategoryRepository;
    public List<BusinessCategoryVO> categoryList() {
        return  businessCategoryRepository.list().stream().map(po->{
            BusinessCategoryVO vo = new BusinessCategoryVO();
            BeanUtils.copyProperties(po,vo);
            return vo;
        }).collect(Collectors.toList());
    }

    public void save(BusinessParam param) throws BusinessException {
        //1.检查业务权限
        checkRole(Roles.ADMIN);
        //2.幂等的新增逻辑
        Integer id = saveOnce(param);
        //3.绑定图片逻辑
//        bindPictures();

    }

    private Integer saveOnce(BusinessParam param) throws BusinessException {
        //线程安全隐患 存在的三个因素
        //a 多线程并发（多个平台管理员 新增）
        //b 共享数据（同一个商家） 现在的业务 不会出现 多个管理员同时新增一个商家
        //c 写操作（增 删 改）
        //insert 数据到 lbs_business 表格 幂等条件 是不允许出现相同名称的商家
        //方案思路：新增写业务 设计幂等 先查 后写 在业务拦截判断
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("business_name",param.getBusinessName());
        //select count(0) from lbs_business where business_name=?
        long count = businessRepository.count(queryWrapper);
        //断言
        Asserts.isTrue(count>0,new BusinessException("-2","商家名称重复"));
        //表单数据 不是 100% 满足 po对象属性要求 手动准备封装
        BusinessPO poParam = new BusinessPO();
        BeanUtils.copyProperties(param,poParam);
        //手动补充3个 状态 2 审核通过 entryTime now auditMark 审核意见
        poParam.setBusinessStatus(2);
        poParam.setEntryTime(new Date());
        poParam.setAuditRemarks("同意");
        businessRepository.save(poParam);
        //持久层框架 mybatis mybatis-plus 根据主键id自增设置 新增成功后 回填id
        return poParam.getId();
    }

    private void checkRole(Roles role) throws BusinessException {
        //读取 认证 传递的userPrinciple 线程和过滤器线程相同
        UserPrinciple userPrinciple = AuthenticationContextUtil.get();
        Asserts.isTrue(userPrinciple==null,new BusinessException("-2","用户认证解析失败"));
        //判断 对象非空的时候 是否和role相等
        Asserts.isTrue(userPrinciple.getRole()!=role,new BusinessException("-2","业务权限不满足"));
    }
}
